package com.bocloud.cmp.service.stats;

import java.math.BigDecimal;
import java.math.RoundingMode;
import java.util.List;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import com.bocloud.cmp.dao.AlarmDao;
import com.bocloud.cmp.dao.CloudServerDao;
import com.bocloud.cmp.dao.CloudVendorDao;
import com.bocloud.cmp.dao.HostSystemDao;
import com.bocloud.cmp.entity.resource.CloudServer;
import com.bocloud.cmp.entity.resource.CloudVendor;
import com.bocloud.cmp.entity.resource.HostSystem;
import com.bocloud.cmp.enums.VMStatus;
import com.bocloud.cmp.enums.VendorType;
import com.bocloud.cmp.interfaces.stats.DashboardStatsService;
import com.bocloud.cmp.service.model.Abstracts;
import com.bocloud.cmp.service.model.AlarmInfo;
import com.bocloud.cmp.service.model.Dashboard;
import com.bocloud.cmp.service.model.OpenstackPlat;
import com.bocloud.cmp.service.model.PlatInfo;
import com.bocloud.cmp.service.model.ResultTrend;
import com.bocloud.cmp.service.model.StatsResult;
import com.bocloud.cmp.service.model.TrendData;
import com.bocloud.cmp.service.model.VmwarePlat;
import com.bocloud.common.model.BsmResult;
import com.bocloud.common.model.Param;
import com.bocloud.common.model.Sign;
import com.bocloud.common.model.SimpleBean;
import com.bocloud.common.utils.MapTools;
import com.google.common.collect.Lists;

@Service("dashboardStatsService")
public class DashboardStatsServiceImpl implements DashboardStatsService {

	private Logger logger = LoggerFactory.getLogger(DashboardStatsServiceImpl.class);
	@Autowired
	private CloudVendorDao cloudVendorDao;
	@Autowired
	private CloudServerDao cloudServerDao;
	@Autowired
	private HostSystemDao hostSystemDao;
	@Autowired
	private AlarmDao alarmDao;

	@Override
	public BsmResult stats() {
		try {
			Abstracts abstracts = getAbstracts();
			VmwarePlat vmwares = getVmwarePlat();
			OpenstackPlat openstacks = getOpenstackPlatf();
			Dashboard dashboard = new Dashboard(abstracts, vmwares, openstacks, null, null);
			return new BsmResult(true, dashboard, "获取信息成功");
		} catch (Exception e) {
			logger.error("Dashboard error:", e);
			return new BsmResult(false, "获取信息失败");
		}
	}

	/**
	 * 统计VMware、openstack、应用和告警的概括信息
	 * 
	 * @return
	 * @throws Exception
	 */
	private Abstracts getAbstracts() throws Exception {
		List<Param> params = Lists.newArrayList();
		int vmwares = 0;
		int vhosts = 0;
		int vservers = 0;
		int openstacks = 0;
		int ohosts = 0;
		int oservers = 0;
		// 所有平台
		List<CloudVendor> vendors = this.cloudVendorDao.listAll();
		for (CloudVendor vendor : vendors) {
			params.clear();
			params.add(new Param(MapTools.simpleMap("vendorId", vendor.getId()), Sign.EQ));
			if (vendor.getType().equals(VendorType.VMWARE.name())) {
				vmwares++;
				vhosts += this.hostSystemDao.count(params);
				params.add(new Param(MapTools.simpleMap("isTemplate", 0), Sign.EQ));
				vservers += this.cloudServerDao.count(params);
			} else if (vendor.getType().equals(VendorType.OPENSTACK.name())) {
				openstacks++;
				ohosts += this.hostSystemDao.count(params);
				oservers += this.cloudServerDao.count(params);
			}
		}
		params.clear();
		int total = this.alarmDao.count(params);
		params.add(new Param(MapTools.simpleMap("level", "DANGER"), Sign.EQ));
		int dangers = this.alarmDao.count(params);
		PlatInfo vmware = new PlatInfo(vmwares, vhosts, vservers);
		PlatInfo openstack = new PlatInfo(openstacks, ohosts, oservers);
		AlarmInfo alarm = new AlarmInfo(total, dangers, total - dangers);
		return new Abstracts(vmware, openstack, null, alarm);
	}

	/**
	 * 统计VMware宿主机、虚拟机开机、关机、异常的数量，及其cpu、内存、磁盘的使用率
	 * 
	 * @return
	 * @throws Exception
	 */
	private VmwarePlat getVmwarePlat() throws Exception {
		int cpuTotal = 0;
		int cpuUsed = 0;
		int memTotal = 0;
		int memUsed = 0;
		int diskTotal = 0;
		int diskUsed = 0;
		int cpuNum = 0;
		List<String> keys = Lists.newArrayList();
		List<TrendData> hostValues = Lists.newArrayList();
		List<TrendData> serverValues = Lists.newArrayList();
		// 宿主机各状态数量集合
		List<String> onlineHosts = Lists.newArrayList();
		List<String> offlineHosts = Lists.newArrayList();
		List<String> disconnHosts = Lists.newArrayList();
		List<String> errorHosts = Lists.newArrayList();
		// 虚拟机各状态数量集合
		List<String> onlineServers = Lists.newArrayList();
		List<String> offlineServers = Lists.newArrayList();
		List<String> disconnServers = Lists.newArrayList();
		List<String> suspendServers = Lists.newArrayList();
		List<String> errorServers = Lists.newArrayList();
		// 所有vmware平台
		List<Param> params = Lists.newArrayList();
		params.add(new Param(MapTools.simpleMap("type", VendorType.VMWARE.name()), Sign.EQ));
		List<SimpleBean> beans = this.cloudVendorDao.list(params, null);
		for (SimpleBean bean : beans) {
			keys.add(bean.getName());
			// 获取宿主机各状态数量
			List<HostSystem> hosts = this.hostSystemDao.listByVendor(bean.getId());
			int onlineHost = 0;
			int offlineHost = 0;
			int errorHost = 0;
			int disconnHost = 0;
			for (HostSystem host : hosts) {
				String status = host.getStatus();
				if (VMStatus.RUNNING.name().equals(status)) {
					onlineHost++;
				} else if (VMStatus.STOPPED.name().equals(status)) {
					offlineHost++;
				} else if ("UNKNOWN".equals(status)) {
					disconnHost++;
				} else {
					errorHost++;
				}
				cpuTotal += host.getCpuTotal();
				cpuUsed += host.getCpuUsed();
				memTotal += host.getMemTotal();
				memUsed += host.getMemUsed();
				diskTotal += host.getDiskTotal();
				diskUsed += host.getDiskUsed();
				cpuNum += host.getCpuNum();

			}
			onlineHosts.add(String.valueOf(onlineHost));
			offlineHosts.add(String.valueOf(offlineHost));
			disconnHosts.add(String.valueOf(disconnHost));
			errorHosts.add(String.valueOf(errorHost));

			// 获取宿主机各状态数量
			List<CloudServer> servers = this.cloudServerDao.listByVid(bean.getId());
			int onlineServer = 0;
			int offlineServer = 0;
			int disconnServer = 0;
			int suspendServer = 0;
			int errorServer = 0;
			for (CloudServer server : servers) {
				String status = server.getStatus();
				if (VMStatus.RUNNING.name().equals(status)) {
					onlineServer++;
				} else if (VMStatus.STOPPED.name().equals(status)) {
					offlineServer++;
				} else if (VMStatus.EXCEPTION.name().equals(status)) {
					errorServer++;
				} else if ("UNKNOWN".equals(status)) {
					disconnServer++;
				} else if (VMStatus.SUSPENDED.name().equals(status)) {
					suspendServer++;
				}
			}

			onlineServers.add(String.valueOf(onlineServer));
			offlineServers.add(String.valueOf(offlineServer));
			disconnServers.add(String.valueOf(disconnServer));
			suspendServers.add(String.valueOf(suspendServer));
			errorServers.add(String.valueOf(errorServer));
		}
		// 宿主机数据
		hostValues.add(new TrendData("ONLINE", onlineHosts));
		hostValues.add(new TrendData("OFFLINE", offlineHosts));
		hostValues.add(new TrendData("UNKNOWN", disconnHosts));
		hostValues.add(new TrendData("ERROR", errorHosts));
		ResultTrend host = new ResultTrend(keys, hostValues);
		// 虚拟机数据
		serverValues.add(new TrendData("ONLINE", onlineServers));
		serverValues.add(new TrendData("OFFLINE", offlineServers));
		serverValues.add(new TrendData("UNKNOWN", disconnServers));
		serverValues.add(new TrendData("SUSPEND", suspendServers));
		serverValues.add(new TrendData("ERROR", errorServers));
		ResultTrend server = new ResultTrend(keys, serverValues);

		Double cpu = 0D;
		if (cpuTotal == 0) {
			cpu = 0D;
		} else {
			cpu = new BigDecimal(cpuUsed * 100).divide(new BigDecimal(cpuTotal), 2, RoundingMode.HALF_UP).doubleValue();
		}
		Double mem = 0D;
		if (memTotal == 0) {
			mem = 0D;
		} else {
			mem = new BigDecimal(memUsed * 100).divide(new BigDecimal(memTotal), 2, RoundingMode.HALF_UP).doubleValue();
		}
		Double disk = 0D;
		if (diskTotal == 0) {
			disk = 0D;
		} else {
			disk = new BigDecimal(diskUsed * 100).divide(new BigDecimal(diskTotal), 2, RoundingMode.HALF_UP)
					.doubleValue();
		}
		return new VmwarePlat(host, server, cpu, mem, disk, cpuNum, memTotal, diskTotal);
	}

	/**
	 * 统计openstack的各状态数量，及其cpu、内存、磁盘的使用率
	 * 
	 * @return
	 * @throws Exception
	 */
	private OpenstackPlat getOpenstackPlatf() throws Exception {
		// cpu、内存、磁盘总量和使用量
		int cpuTotal = 0;
		int cpuUsed = 0;
		int memTotal = 0;
		int memUsed = 0;
		int diskTotal = 0;
		int diskUsed = 0;
		int cpuNum = 0;
		// 宿主机各状态数量
		int onlineHost = 0;
		int offlineHost = 0;
		int errorHost = 0;
		// 虚拟机各状态数量
		int onlineServer = 0;
		int offlineServer = 0;
		int errorServer = 0;
		List<StatsResult> hosts = Lists.newArrayList();
		List<StatsResult> servers = Lists.newArrayList();
		// 所有vmware平台
		List<Param> params = Lists.newArrayList();
		params.add(new Param(MapTools.simpleMap("type", VendorType.OPENSTACK.name()), Sign.EQ));
		List<SimpleBean> beans = this.cloudVendorDao.list(params, null);
		for (SimpleBean bean : beans) {
			// 获取宿主机各状态数量
			List<HostSystem> hostSystems = this.hostSystemDao.listByVendor(bean.getId());
			for (HostSystem host : hostSystems) {
				String status = host.getStatus();
				if (VMStatus.RUNNING.name().equals(status)) {
					onlineHost++;
				} else if (VMStatus.STOPPED.name().equals(status)) {
					offlineHost++;
				} else if (VMStatus.EXCEPTION.name().equals(status)) {
					errorHost++;
				}
				cpuTotal += host.getCpuTotal();
				cpuUsed += host.getCpuUsed();
				memTotal += host.getMemTotal();
				memUsed += host.getMemUsed();
				diskTotal += host.getDiskTotal();
				diskUsed += host.getDiskUsed();
				cpuNum += host.getCpuNum();
			}

			// 获取宿主机各状态数量
			List<CloudServer> cloudServers = this.cloudServerDao.listByVid(bean.getId());
			for (CloudServer server : cloudServers) {
				String status = server.getStatus();
				if (VMStatus.RUNNING.name().equals(status)) {
					onlineServer++;
				} else if (VMStatus.STOPPED.name().equals(status)) {
					offlineServer++;
				} else if (VMStatus.EXCEPTION.name().equals(status)) {
					errorServer++;
				}
			}

		}
		// 宿主机数据
		hosts.add(new StatsResult("ONLINE", onlineHost));
		hosts.add(new StatsResult("OFFLINE", offlineHost));
		hosts.add(new StatsResult("ERROR", errorHost));
		// 虚拟机数据
		servers.add(new StatsResult("ONLINE", onlineServer));
		servers.add(new StatsResult("OFFLINE", offlineServer));
		servers.add(new StatsResult("ERROR", errorServer));

		Double cpu = 0D;
		if (cpuTotal == 0) {
			cpu = 0D;
		} else {
			cpu = new BigDecimal(cpuUsed * 100).divide(new BigDecimal(cpuTotal), 2, RoundingMode.HALF_UP).doubleValue();
		}
		Double mem = 0D;
		if (memTotal == 0) {
			mem = 0D;
		} else {
			mem = new BigDecimal(memUsed * 100).divide(new BigDecimal(memTotal), 2, RoundingMode.HALF_UP).doubleValue();
		}
		Double disk = 0D;
		if (diskTotal == 0) {
			disk = 0D;
		} else {
			disk = new BigDecimal(diskUsed * 100).divide(new BigDecimal(diskTotal), 2, RoundingMode.HALF_UP)
					.doubleValue();
		}
		return new OpenstackPlat(hosts, servers, cpu, mem, disk, cpuNum, memTotal, diskTotal);
	}

}
